﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Office = Microsoft.Office.Core;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Workitem = Microsoft.TeamFoundation.WorkItemTracking.Client.WorkItem;
using WordTemplate1.Methodes;
using WordTemplate1.Objets;
using Microsoft.Office.Interop.Word;
using System.ComponentModel;
using System.Diagnostics;
using System.Collections;
using Methodes.WordTemplate1;
using WordTemplate1.Formulaire;
using Microsoft.TeamFoundation.WorkItemTracking.Controls;

namespace WordTemplate1
{
    public partial class UCPanel : UserControl
    {

        private List<WorkItem> listWorkItem;
        private List<Element> listElement = new List<Element>();

        BackgroundWorker bgwWorkItem = new BackgroundWorker();


        public List<Element> ListElement
        {
            get { return listElement; }
            set { listElement = value; }
        }

        private List<String> type;
        private WorkItem wi = null;

        /// <summary>
        /// Récupération des workitems sous forme de list<>
        /// </summary>
        public List<WorkItem> WorkItems
        {
            get { return listWorkItem; }
        }
        public Workitem WorkItem;

        /// <summary>
        /// Liste des requêtes 
        /// </summary>
        private List<QueryItem> listeQuery = new List<QueryItem>();

        /// <summary>
        /// Liste des requêtes 
        /// </summary>
        public List<QueryItem> ListeQuery
        {
            get { return listeQuery; }
            set
            {
                listeQuery = value;
                string query = Globals.ThisDocument.ReadDocumentProperty("Query");
                // Met à jour la liste des requêtes
                cbxQueries.DataSource = listeQuery;
                cbxQueries.DisplayMember = "Name";

                if (!String.IsNullOrEmpty(query))
                    cbxQueries.Text = query;

            }
        }

        /// <summary>
        /// Liste des workitem à afficher
        /// </summary>
        public WorkItemCollection ListWorkItem
        {
            set
            {
                txtCountWI.Text = "Nb Workitem : 0 ";

                List<ContentControl> diff = new List<ContentControl>();

                listWorkItem = (List<WorkItem>)value.Cast<WorkItem>().ToList();

                if (listWorkItem != null)
                {
                    var LinqResult = from search in listWorkItem
                                     from cc in Globals.ThisDocument.ContentControls.Cast<ContentControl>()
                                     where cc.Title.Contains(search.Id.ToString())
                                     select search;

                }
                trvWI.Nodes.Clear();

                type = (from t in listWorkItem.Cast<WorkItem>()
                        select t.Type.Name).Distinct().ToList();

                ChargementData();
                txtCountWI.Text = "Nb Workitem : " + listWorkItem.Count.ToString();
            }
        }

        /// <summary>
        /// Chargement des données
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void ChargementData()
        {
            foreach (string value in type)
            {
                TreeNode treeType = new TreeNode(value);
                AddWi(value, treeType);
                SetAddTreeNode(treeType);
            }


            // Vérification de la présence des éléments dans le document
            // Permet de savoir si le document est à jour par rapport au élément du serveur
            foreach (ContentControl cc in Globals.ThisDocument.ContentControls)
            {
                var elements = (from search in this.listElement
                                where search.Type == TypeElement.Field
                                select search).Cast<EField>();

                if (elements.Count() > 0)
                {
                    var elements2 = from search in elements
                                    where cc.Title != null
                                    && cc.Title.Contains(search.ReferenceName)
                                    && cc.Title.Contains(search.Workitem.Id.ToString())
                                    select search;

                    foreach (EField element in elements2)
                    {
                        element.AddContentControl(cc);

                        if (cc.Range.Text.Trim().ToUpperInvariant().CompareTo(element.ValueTFS.Trim().ToUpperInvariant()) != 0)
                        {
                            element.Modify(cc);
                        }
                    }
                }
            }
        }

        private void AddWi(string t, TreeNode treeType)
        {
            var LinqResult = from search in listWorkItem.Cast<WorkItem>()
                             where search.Type.Name == t
                             select search;

            //Variable permettant de faire défiler la progressbar
            int value = 1;
            int max = LinqResult.Count();
            int count = 1;

            foreach (WorkItem work in LinqResult)
            {
                value = count * 100 / max;
                count++;

                SetWaite(value);

                TreeNode tree = null;

                tree = new TreeNode(work.Title);


                TreeNode tnAttachement = new TreeNode("Attachement", 6, 6);
                tree.Nodes.Add(tnAttachement);
                tnAttachement.ContextMenuStrip = cmsPJ;

                TreeNode tnWorkItemLinks = new TreeNode("WorkItemLinks", 5, 5);
                tree.Nodes.Add(tnWorkItemLinks);

                TreeNode tnLinks = new TreeNode("Links", 5, 5);
                tnLinks.ContextMenuStrip = cmsLink;
                tree.Nodes.Add(tnLinks);

                if (work.Attachments.Count > 0)
                {
                    foreach (Attachment attachment in work.Attachments)
                    {
                        if (Images.IsImage(attachment.Extension))
                        {
                            EAPicture element = new EAPicture(attachment);
                            element.Workitem = work;
                            TreeNode tn = element.Tree;
                            tnAttachement.Nodes.Add(tn);
                            this.listElement.Add(element);
                        }
                    }
                }

                if (work.WorkItemLinks.Count > 0)
                {
                    foreach (WorkItemLink wil in work.WorkItemLinks)
                    {
                        TFS tfs = new TFS();

                        WorkItem wi = tfs.GetWorkitemByID(wil.SourceId);

                        //Element element = new Element();
                        //element.Workitem = work;
                        //TreeNode tn = element.Tree;
                        //this.listElement.Add(element);

                        //tnWorkItemLinks.Nodes.Add(tn);

                        //DetailWI(wi, tn);

                    }
                }
                if (work.Links.Count > 0)
                {
                    foreach (Link l in work.Links)
                    {
                        TFS tfs = new TFS();

                        if (l.BaseType == BaseLinkType.RelatedLink)
                        {
                            WorkItem wi = tfs.GetWorkitemByID(((RelatedLink)l).RelatedWorkItemId);

                            ELink element = new ELink(l, wi);
                            this.listElement.Add(element);
                            TreeNode tn = element.Tree;

                            tn.ContextMenuStrip = cmsRemoveLink;
                            tnLinks.Nodes.Add(tn);

                            DetailWI(wi, tn);

                        }
                    }
                }

                DetailWI(work, tree);


                tree.Tag = work;

                treeType.Nodes.Add(tree);
            }


            SetWaite(0);
        }


        /// <summary>
        /// Déléguate permettant l'interactionavec les composants de l'add-in
        /// </summary>
        /// <param name="text"></param>
        delegate void SetCallback(int value);

        /// <summary>
        /// Déléguate permettant l'interactionavec le treeview
        /// </summary>
        /// <param name="text"></param>
        delegate void SetAddTN(TreeNode text);


        /// <summary>
        /// Méthode a appeler pour afficher une information d'attente dans le treeview
        /// </summary>
        /// <param name="text"></param>
        private void SetWaite(int value)
        {
            if (this.progressBar.InvokeRequired)
            {
                SetCallback d = new SetCallback(SetWaite);
                this.progressBar.Invoke(d, new object[] { value });
            }
            else
            {
                this.progressBar.Value = value;
            }
        }

        /// <summary>
        /// Méthode a appeler pour afficher une information d'attente dans le treeview
        /// </summary>
        /// <param name="text"></param>
        private void SetAddTreeNode(TreeNode node)
        {
            if (this.trvWI.InvokeRequired)
            {
                SetAddTN d = new SetAddTN(SetAddTreeNode);
                this.trvWI.Invoke(d, new object[] { node });
            }
            else
            {
                this.trvWI.Nodes.Add(node);
                this.trvWI.Refresh();
            }
        }
        /// <summary>
        /// Permet la création du détail d'un workitem
        /// </summary>
        /// <param name="work"></param>
        /// <param name="tree"></param>
        private static void DetailWI(WorkItem work, TreeNode tree)
        {
            Hashtable ht = new Hashtable();

            foreach (Microsoft.TeamFoundation.WorkItemTracking.Client.Field f in work.Fields)
            {
                EField element = new EField(f);

                Globals.ThisDocument.taskPanel.listElement.Add(element);

                if (f.Value != null)
                {
                    string categorie = SchemaWI.GetCategorie(work, f);

                    if (String.IsNullOrEmpty(categorie))
                        tree.Nodes.Add(element.Tree);

                    else if (categorie == Globals.ThisDocument.IdentifiantContent)
                    {
                        if (ht.ContainsKey("Autre"))
                        {
                            TreeNode tn = ht["Autre"] as TreeNode;
                            tn.Nodes.Add(element.Tree);
                        }
                        else if (!ht.ContainsKey(categorie))
                        {
                            TreeNode tn = new TreeNode("Autre");
                            ht.Add("Autre", tn);
                            tn.Nodes.Add(element.Tree);
                            tree.Nodes.Add(tn);
                        }
                    }
                    else if (ht.ContainsKey(categorie))
                    {
                        TreeNode tn = ht[categorie] as TreeNode;
                        tn.Nodes.Add(element.Tree);
                    }
                    else if (!ht.ContainsKey(categorie))
                    {
                        TreeNode tn = new TreeNode(categorie);
                        ht.Add(categorie, tn);
                        tn.Nodes.Add(element.Tree);
                        tree.Nodes.Add(tn);
                    }
                }
            }
        }


        public UCPanel()
        {
            InitializeComponent();

            ActiveCompoment(false);
        }

        /// <summary>
        /// Permet d'insertion d'un élément d'un workitem
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void trvWI_DoubleClick(object sender, EventArgs e)
        {
            if (trvWI.SelectedNode != null)
            {
                if (trvWI.SelectedNode.Tag != null)
                {
                    if (trvWI.SelectedNode.Tag is EField)
                    {
                        EField f = (EField)trvWI.SelectedNode.Tag;

                        if (f.Type == TypeElement.Field)
                        {
                            Contents.AddContentText(f);
                        }
                    }
                    else if (trvWI.SelectedNode.Tag is EAPicture)
                    {
                        EAPicture f = (EAPicture)trvWI.SelectedNode.Tag;

                        if (Images.IsImage(f.Attachement.Extension))
                        {
                            Globals.ThisDocument.AddImage(f.Attachement.Uri.AbsoluteUri);
                        }
                    }
                }
            }
        }


        /// <summary>
        /// Methode permettant d'informer du contenu de l'élément sélectionné dans la liste
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void trvWI_AfterSelect(object sender, TreeViewEventArgs e)
        {
            if (trvWI.SelectedNode != null)
            {
                if (trvWI.SelectedNode.Tag != null)
                {
                    if (trvWI.SelectedNode.Tag is EField)
                    {
                        EField f = (EField)trvWI.SelectedNode.Tag;

                        txtDetail.Text = f.ValueTFS;
                    }
                    if (trvWI.SelectedNode.Tag is Workitem)
                    {
                        Workitem f = (Workitem)trvWI.SelectedNode.Tag;
                        txtDetail.Text = f.Description.ToString();
                    }
                }
            }
        }

        /// <summary>
        /// Actualise les workitems depuis TFS
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnActualiser_Click(object sender, EventArgs e)
        {
            Actualise();
        }

        internal void Actualise()
        {
            TFS tfs = new TFS();

            // Récupération de la requête définit dans la liste de choix
            if (String.IsNullOrEmpty(cbxQueries.Text))
            {
                tfs.ActualiserWI(true);
            }
            else
            {
                var LinqResult = from q in listeQuery
                                 where q.Name == cbxQueries.Text
                                 select q;

                if (LinqResult.Count() > 0)
                    tfs.ActualiserWI(true, LinqResult.First());
            }

            // Vérification de la présence des éléments dans le document
            // Permet de savoir si le document est à jour par rapport au élément du serveur
            foreach (ContentControl cc in Globals.ThisDocument.ContentControls)
            {
                if (cc.GetElement() != null)
                {
                    if (cc.GetElement() is EField)
                    {
                        EField element = cc.GetElement() as EField;

                        if (string.Compare(element.ValueTFS, cc.Range.Text, true) != 0)
                        {
                            element.IsModify = true;
                        }
                    }
                }
            }

            Globals.ThisDocument.taskInformation.ActualiseInformation();
        }

        private void btnSearch_Click(object sender, EventArgs e)
        {

            TFS tfs = new TFS();

            this.listView1.Items.Clear();

            wi = tfs.GetWorkitemByID(int.Parse(txtID.Text));

            if (wi != null)
            {
                foreach (Microsoft.TeamFoundation.WorkItemTracking.Client.Field item in wi.Fields)
                {
                    ListViewItem lvi;
                    lvi = new ListViewItem(item.Name);
                    lvi.Tag = item;
                    if (item.Value != null)
                        lvi.SubItems.Add(item.Value.ToString());
                    else
                        lvi.SubItems.Add(String.Empty);

                    lvi.SubItems.Add(item.ReferenceName);
                    lvi.SubItems.Add(item.WorkItem.Id.ToString());
                    lvi.Tag = item;
                    this.listView1.Items.Add(lvi);
                }
            }

        }

        private void supprimerLaPJToolStripMenuItem_Click(object sender, EventArgs e)
        {
            WorkItem work = GetSelectedWI();

            work.Open();

            //work.Attachments.Remove(this.Attachement);

            if (work.IsValid())
                work.Save();

            Globals.ThisDocument.taskPanel.Actualise();
        }

        private void appliquerLeWorkitemToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (Globals.ThisDocument.Application.Selection.Range.ContentControls.Count == 0)
            {
                MessageBox.Show("No selection in the document does apply the information selected WI");
            }
            else
            {
                Workitem work = GetSelectedWI();

                if (work != null)
                {
                    foreach (ContentControl cc in Globals.ThisDocument.Application.Selection.Range.ContentControls)
                    {
                        // Vérification de la présence d'un titre
                        if (!String.IsNullOrEmpty(cc.Title))
                        {
                            string[] information = cc.Title.Split('|');
                            // Vérification du nombre d'élément
                            if (information.Count() > 2)
                            {
                                // Vérification de la présence de l'identifiant 
                                if (information[0] == Globals.ThisDocument.IdentifiantContent)
                                {
                                    var LinqResult = from search in
                                                         (from search2 in this.listElement where search2.Type == TypeElement.Field select search2).Cast<EField>()
                                                     where search.Workitem.Id == work.Id
                                                     select search;

                                    if (LinqResult != null)
                                    {
                                        var field = from search in LinqResult
                                                    where search.ReferenceName == information[2]
                                                    select search;
                                        if (field.Count() > 0)
                                        {
                                            bool locked = cc.LockContents;
                                            if (locked)
                                            {
                                                cc.LockContents = false;
                                            }
                                            cc.Title = Globals.ThisDocument.IdentifiantContent + "|" + work.Id + "|" + information[2];
                                            cc.Range.Text = field.First().ValueTFS.ToString();
                                            field.First().AddContentControl(cc);

                                            cc.LockContents = locked;
                                        }
                                        else
                                        {
                                            bool locked = cc.LockContents;
                                            if (locked)
                                            {
                                                cc.LockContents = false;
                                            }
                                            cc.Range.Text = String.Empty;

                                            cc.LockContents = locked;
                                        }
                                    }
                                    else
                                    {
                                        bool locked = cc.LockContents;
                                        if (locked)
                                        {
                                            cc.LockContents = false;
                                        }
                                        cc.Range.Text = String.Empty;

                                        cc.LockContents = locked;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        /// <summary>
        /// Permet de récupérer le WI actuellement sélectionné
        /// </summary>
        /// <returns></returns>
        private WorkItem GetSelectedWI()
        {
            if (trvWI.SelectedNode != null)
            {
                if (trvWI.SelectedNode.Tag != null)
                {
                    TreeNode tn = trvWI.SelectedNode;

                    while (!(tn.Tag is WorkItem))
                    {
                        tn = tn.Parent;
                    }

                    if (tn.Tag is WorkItem)
                    {
                        return (WorkItem)tn.Tag;
                    }
                }
                else
                {
                    if (trvWI.SelectedNode.Parent.Tag is WorkItem)
                    {
                        WorkItem wi = (WorkItem)trvWI.SelectedNode.Parent.Tag;
                        return wi;
                    }
                    while (!(trvWI.SelectedNode.Parent.Tag is WorkItem))
                    {
                        if (trvWI.SelectedNode.Tag is WorkItem)
                        {
                            return (WorkItem)trvWI.SelectedNode.Tag;
                        }
                    }
                }
            }
            return null;
        }

        /// <summary>
        /// Permet d'ouvrir le WI dans IE
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ouvrirLeWorkitemToolStripMenuItem_Click(object sender, EventArgs e)
        {
            using (CreateWorkitem frm = new CreateWorkitem(GetSelectedWI(), true))
            {
                frm.ShowDialog();
            }
        }

        /// <summary>
        /// Permet de réactivé chaque composant après connexion au serveur
        /// </summary>
        /// <param name="desactive"></param>
        internal void ActiveCompoment(bool desactive = true)
        {
            foreach (Control c in this.Controls)
            {
                c.Enabled = desactive;
            }
        }

        private void ajoutDunePièceJointeToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Workitem work = GetSelectedWI();

            AddElementInWork aeiw = new AddElementInWork();
            aeiw.Work = work;

            aeiw.ShowDialog();

        }

        private void ajouterUnLienToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Workitem work = GetSelectedWI();

            AddLink al = new AddLink();
            al.Work = work;

            al.ShowDialog();
        }

        private void supprimerLeLienToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (trvWI.SelectedNode != null)
            {
                if (trvWI.SelectedNode.Tag != null)
                {
                    Workitem work = GetSelectedWI();

                    if (work != null)
                    {
                        Link l = null;

                        foreach (Link ll in work.Links)
                        {
                            if (((RelatedLink)ll).RelatedWorkItemId == (int)trvWI.SelectedNode.Tag)
                                l = ll;
                        }

                        if (l != null)
                        {
                            work.Open();

                            work.Links.Remove(l);

                            if (work.IsValid())
                                work.Save();

                            Globals.ThisDocument.taskPanel.Actualise();
                        }
                    }
                }
            }
        }

        private void listView1_DoubleClick(object sender, EventArgs e)
        {

            ListViewItem lvi = listView1.SelectedItems[0];
            string RN = lvi.SubItems[2].Text;
            int ID = int.Parse(lvi.SubItems[3].Text);

            var linqResult = (from search in
                                  (from search2 in this.listElement where search2.Type == TypeElement.Field select search2).Cast<EField>()
                              where search.ReferenceName == RN
                              && search.Workitem.Id == ID
                              select search).FirstOrDefault();

            if (linqResult != null)
                Contents.AddContentText(linqResult);
            else
                Contents.AddContentText(new EField(lvi.Tag as Microsoft.TeamFoundation.WorkItemTracking.Client.Field));
        }

        private void cbxQueries_SelectedIndexChanged(object sender, EventArgs e)
        {
            Globals.ThisDocument.AddProperties("Query", cbxQueries.Text, true);
        }
    }
}
